package cn.iocoder.yudao.module.book.service.app;

import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.book.controller.app.vo.AppBookRecordInfoVO;
import cn.iocoder.yudao.module.book.controller.app.vo.AppBookRecordReqVO;
import cn.iocoder.yudao.module.book.controller.app.vo.AppBookRecordRespVO;
import cn.iocoder.yudao.module.book.controller.app.vo.AppBookShelfRespVO;
import cn.iocoder.yudao.module.book.dal.dataobject.book.BookDO;
import cn.iocoder.yudao.module.book.dal.dataobject.bookshelf.BookShelfDO;
import cn.iocoder.yudao.module.book.dal.dataobject.bookshelfcatalogue.BookShelfCatalogueDO;
import cn.iocoder.yudao.module.book.dal.dataobject.record.RecordDO;
import cn.iocoder.yudao.module.book.dal.mysql.book.BookMapper;
import cn.iocoder.yudao.module.book.dal.mysql.bookshelf.BookShelfMapper;
import cn.iocoder.yudao.module.book.dal.mysql.bookshelfcatalogue.BookShelfCatalogueMapper;
import cn.iocoder.yudao.module.book.dal.mysql.record.RecordMapper;
import jakarta.annotation.Resource;

@Service
public class AppBookRecordServiceImpl implements AppBookRecordService {

    private static final long ONE_MINUTE = 60;
    private static final long ONE_HOUR = 60 * ONE_MINUTE;
    private static final long ONE_DAY = 24 * ONE_HOUR;
    private static final long ONE_MONTH = 30 * ONE_DAY; // 近似
    private static final long ONE_YEAR = 365 * ONE_DAY; // 近似
    @Resource
    private RecordMapper bookRecordMapper;

    @Resource
    private BookMapper bookMapper;

    @Resource
    private BookShelfMapper bookShelfMapper;

    @Resource
    private BookShelfCatalogueMapper bookShelfCatalogueMapper;

    /**
     * 把两个 LocalDateTime 转成自然描述
     */
    public static String format(LocalDateTime from) {
        return format(from, LocalDateTime.now());
    }

    public static String format(LocalDateTime from, LocalDateTime to) {
        long seconds = Duration.between(from, to).getSeconds();
        if (seconds < ONE_MINUTE) {
            return "刚刚";
        } else if (seconds < ONE_HOUR) {
            long minutes = seconds / ONE_MINUTE;
            return minutes + "分钟前";
        } else if (seconds < ONE_DAY) {
            long hours = seconds / ONE_HOUR;
            return hours + "小时前";
        } else if (seconds < ONE_MONTH) {
            long days = seconds / ONE_DAY;
            return days + "天前";
        } else if (seconds < ONE_YEAR) {
            long months = seconds / ONE_MONTH;
            return months + "月前";
        } else {
            long years = seconds / ONE_YEAR;
            return years + "年前";
        }
    }

    @Override
    public AppBookRecordInfoVO getBookRecordList() {
        AppBookRecordInfoVO bookRecordInfoVO = new AppBookRecordInfoVO();
        LambdaQueryWrapper<RecordDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordDO::getUserId, SecurityFrameworkUtils.getLoginUserId());
        List<RecordDO> bookRecordDOList = bookRecordMapper.selectList(queryWrapper);
        if (bookRecordDOList != null && !bookRecordDOList.isEmpty()) {
            // 查询 createTime 最早的记录
            RecordDO earliestRecord = bookRecordMapper.selectEarliestRecord();
            // 获取 createTime
            LocalDateTime createTime = earliestRecord.getCreateTime();
            // 计算已阅读的天数
            long daysSinceCreation = ChronoUnit.DAYS.between(createTime, LocalDateTime.now());
            // 设置已阅读天数
            bookRecordInfoVO.setReadingDays((int)daysSinceCreation);
            // 设置加入天数
            bookRecordInfoVO.setNumberOfDayAdded((int)daysSinceCreation);
            // 设置今日阅读量
            bookRecordInfoVO.setTodayReadingTotal(bookRecordMapper.countTodayRecords());
            // 设置本周阅读量
            bookRecordInfoVO.setThisWeekReadingTotal(bookRecordMapper.countThisWeekRecords());
            List<AppBookRecordRespVO> bookRecordRespVOList = new ArrayList<>();
            bookRecordDOList.forEach(item -> {
                AppBookRecordRespVO resp = BeanUtils.toBean(item, AppBookRecordRespVO.class);
                resp.setReadingTime(format(item.getCreateTime()));
                BookDO bookDO = bookMapper.selectById(item.getBookId());
                if (Objects.nonNull(bookDO)) {
                    resp.setBookName(bookDO.getBookName());
                    resp.setCover(bookDO.getCover());
                }
                bookRecordRespVOList.add(resp);
            });
            bookRecordInfoVO.setBookRecordList(bookRecordRespVOList);
        }
        return bookRecordInfoVO;
    }

    @Override
    public Long createBookRecord(AppBookRecordReqVO bookRecordReqVO) {

        LambdaQueryWrapper<RecordDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordDO::getBookId, bookRecordReqVO.getBookId());
        queryWrapper.eq(RecordDO::getUserId, SecurityFrameworkUtils.getLoginUserId());

        RecordDO recordDO = BeanUtils.toBean(bookRecordReqVO, RecordDO.class);
        recordDO.setUserId(SecurityFrameworkUtils.getLoginUserId());
        BookDO bookDO = bookMapper.selectById(bookRecordReqVO.getBookId());
        if (Objects.isNull(bookDO))
            throw new ServiceException(9999, "书籍不存在");
        BookShelfDO bookShelfDO = bookShelfMapper.selectById(bookDO.getBookShelfId());
        if (Objects.isNull(bookShelfDO))
            throw new ServiceException(9999, "绘本集不存在");
        BookShelfCatalogueDO bookShelfCatalogueDO = bookShelfCatalogueMapper.selectById(bookShelfDO.getCatalogueId());
        if (Objects.isNull(bookShelfCatalogueDO))
            throw new ServiceException(9999, "绘本集目录不存在");
        recordDO.setCatalogue(String.valueOf(bookShelfCatalogueDO.getType()));
        bookRecordMapper.insert(recordDO);
        return recordDO.getId();
    }

    @Override
    public void deleteBookRecord(Long id) {
        bookRecordMapper.deleteById(id);
    }

    @Override
    public void deleteAllBookRecord() {
        bookRecordMapper.delete(new QueryWrapperX<RecordDO>().eq("creator", getLoginUserId()));
    }

    @Override
    public List<AppBookShelfRespVO> queryMyRecentlyReadBooks(String type) {
        List<AppBookShelfRespVO> bookShelfRespVOList = new ArrayList<>();
        LambdaQueryWrapper<RecordDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordDO::getUserId, SecurityFrameworkUtils.getLoginUserId()).eq(RecordDO::getCatalogue, type).orderByDesc(RecordDO::getUpdateTime).last("LIMIT 3");
        List<RecordDO> recordList = bookRecordMapper.selectList(queryWrapper);
        if (CollUtil.isNotEmpty(recordList)) {
            recordList.forEach(item -> {
                BookDO bookDO = bookMapper.selectById(item.getBookId());
                if (Objects.nonNull(bookDO)) {
                    BookShelfDO bookShelfDO = bookShelfMapper.selectById(bookDO.getBookShelfId());

                    LambdaQueryWrapper<BookDO> bookQueryWrapper = new LambdaQueryWrapper<>();
                    bookQueryWrapper.eq(BookDO::getBookShelfId, bookShelfDO.getId());
                    Long count = bookMapper.selectCount(bookQueryWrapper);
                    AppBookShelfRespVO bookShelfRespVO = BeanUtils.toBean(bookShelfDO, AppBookShelfRespVO.class);
                    bookShelfRespVO.setBookCount(String.valueOf(count));
                    bookShelfRespVOList.add(bookShelfRespVO);
                }
            });
        }
        return bookShelfRespVOList;
    }

    @Override
    public Integer clearBookReadingHistory() {
        LambdaQueryWrapper<RecordDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordDO::getUserId, SecurityFrameworkUtils.getLoginUserId());
        return bookRecordMapper.delete(queryWrapper);
    }
}